from functools import wraps
from flask.app import Flask
from flask.globals import request
#from flask_cors import CORS
from flask import Blueprint, jsonify
import service_impl
import traceback
import os
import utils
from entities import MessageData

#初始化app

app = Blueprint("app", __name__)
flask_app = Flask(__name__, instance_relative_config=True, template_folder=os.getcwd())

#CORS(app, supports_credentials=True)  # 设置允许跨域访问

def readJsonData():
    #从请求对象中读取请求的json数据
    try:
        json_data = request.get_json(force=True)#
        if json_data:
            return json_data
    except:
        traceback.print_exc()
    return {}

def ok_data(data=None):
    #返回正常的json数据
    ret = {"code": 0, "msg": "ok"}
    if data!=None and isinstance(data, dict):
        for key in data.keys():
            ret[key] = data[key]
    return jsonify(ret)

def error_data(code, msg):
    #错误的数据
    data = {"code": code, "msg": msg}
    return jsonify(data)

def msissing_parameters_error():
    #错误的参数错误
    return error_data(400, "Missing parameters.")

def illegal_access_error():
    #非法访问
    return error_data(340, "Illegal access.")

def error_data_invalidate_token():
    #错误的令牌
    print('error 330')
    return error_data(code = 330, msg = '错误的令牌')

def error_data_timeout_token():
    #超时
    return error_data(code = 300, msg = '会话超时')

def verify_access_token(token):
    return service_impl.verify_user_token(token) or service_impl.verify_device_token(token)

def verify_token(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        #验证token
        #data = readJsonData()
        token = request.headers.get("token")
        #print(f'verify token:{token}')
        #print(data)
        if token:
            if verify_access_token(token=token):
                return func(*args, **kwargs)
            else:
                return error_data_timeout_token()
        return error_data_invalidate_token()
    return wrapper

def current_user_id():
    #获取当前访问的用户id
    token = request.headers.get("token")
    if token:
        return service_impl.get_user_id_by_token(token)
    return None

def current_device_id():
    #获取当前访问的设备Id
    token = request.headers.get("token")
    if token:
        return service_impl.get_device_id_by_token(token)
    return None

@app.route('/', methods=['GET', 'POST'])
def hello():
    #print(request.form)
    #print(request.get_data())
    return '<h1 style="color:blue">If you saw this page，indicates that it has started normally...</h1>'

#设备验证
@app.route('/device/verify',methods=['POST'])
def device_verify():
    data = readJsonData()
    key = data.get("key")
    if key:
        try:
            token = service_impl.device_verify(key)
            return ok_data({'token': token})
        except Exception as e:
            traceback.print_exc()
            return error_data(-1, str(e))
    else:
        return msissing_parameters_error()

@app.route('/device/beat',methods=['POST'])
@verify_token
def device_beat():
    #设备心跳
    token = request.headers.get("token")
    if token and service_impl.verify_device_token(token):
        try:
            data = readJsonData()
            data = service_impl.device_beat(data)
            return ok_data(data)
        except Exception as e:
            traceback.print_exc()
            return error_data(-1, str(e))
    else:
        #print(token)
        return illegal_access_error()

@app.route('/iot/login',methods=['POST','GET'])
def mgr_login():
    #用户登录
    data = readJsonData()
    name = data.get("username")
    pwd = data.get("password")
    if name and pwd:
        try:
            token = service_impl.user_login(name, pwd)
            return ok_data({'data':{'token': token}})
        except Exception as e:
            traceback.print_exc()
            return error_data(-1, str(e))
    else:
        return msissing_parameters_error()
    
@app.route('/iot/time',methods=['POST'])
def get_server_time():
    #返回服务器时间
    
    return ok_data({'time': utils.rtc_now_date_time()})

@app.route('/learn/time',methods=['GET', 'POST'])
def get_learn_server_time():
    #返回服务器时间
    return ok_data({'time': utils.now_str()})

@app.route('/iot/sendmessage',methods=['POST'])
@verify_token
def iot_sendmessage():
    #发送消息
    token = request.headers.get("token")
    if token: 
        sender = None
        device_id = None
        if service_impl.verify_user_token(token):
            sender = MessageData.SENDER_USER
        if service_impl.verify_device_token(token):
            sender = MessageData.SENDER_DEVICE
            device_id = service_impl.get_device_id_by_token(token)
        if sender != None:
            data = readJsonData()
            try:
                data['sender'] = sender
                if device_id:
                    data['device_id'] = device_id
                _id = service_impl.send_message(data)
                return ok_data({"id": _id})
            except Exception as e:
                traceback.print_exc()
                return error_data(str(e))
        else:
            return illegal_access_error()
    else:
        #print(token)
        return illegal_access_error()

@app.route('/iot/getlastmessage',methods=['POST'])
@verify_token
def iot_get_last_message():
    #获取最新的消息
    #发送消息
    token = request.headers.get("token")
    if token: 
        data = readJsonData()
        device_id = None
        if service_impl.verify_user_token(token):
            devicd_id = data.get("device_id")
        if service_impl.verify_device_token(token):
            device_id = service_impl.get_device_id_by_token(token)
        if(device_id==None):
            device_id = data.get('device_id')
        action = data.get("action")
        
        if device_id!=None and action!=None:
            try:
                data = service_impl.get_last_message(device_id=device_id, action=action)
                return ok_data(data)
            except Exception as e:
                traceback.print_exc()
                return error_data(-1, str(e))
        else:
            return msissing_parameters_error()
    else:
        #print(token)
        return illegal_access_error()

@app.route('/iot/getmessages',methods=['POST'])
@verify_token
def iot_get_messages():
    #获取最新的消息
    #发送消息
    token = request.headers.get("token")
    if token: 
        data = readJsonData()
        sender = None
        device_id = None
        sender = data.get("sender")
        if service_impl.verify_user_token(token):
            device_id = data.get("device_id")
        if service_impl.verify_device_token(token):
            device_id = service_impl.get_device_id_by_token(token)
        if sender != None or device_id!=None:
            action = data.get("action")
            page_size = data.get("page_size")
            page_no = data.get("page_no")
            try:
                data = service_impl.get_message_list(
                    device_id=device_id,
                    sender=sender,
                    action=action,
                    page_size=page_size,
                    page_no=page_no
                )
                return ok_data({"data": data})
            except Exception as e:
                traceback.print_exc()
                return error_data(str(e))
        else:
            return illegal_access_error()
    else:
        #print(token)
        return illegal_access_error()

@app.route('/iot/get-device-types',methods=['POST'])
@verify_token
def iot_get_devicetypes():
    #获取设备类型
    return ok_data({'data':[{
        'dtid':'cat_fedeeding',
        'name': '猫咪喂食器',
        'icon': 'cat_feeder.png'
    }]})

@app.route('/iot/get-device',methods=['POST'])
@verify_token
def iot_get_device():
    #获取设备类型
    data = readJsonData()
    if(data):
        device_id = data.get("device_id")
    else:
        device_id = None
    if device_id:
        data = service_impl.get_device_by_id(device_id=device_id)
        if data:
            return ok_data({'data': data})
        else:
            return ok_data()
    return msissing_parameters_error()

@app.route('/iot/get-devices', methods=['POST'])
@verify_token
def iot_get_devices():
#获取设备列表
    token = request.headers.get("token")
    if token: 
        user_id = service_impl.get_user_id_by_token(token)
        if user_id:
            try:
                return ok_data({'data':service_impl.get_devices_by_user(user_id=user_id)})
            except Exception as e:
                traceback.print_exc()
                return error_data(str(e))
        else:
            return illegal_access_error()
    else:
        #print(token)
        return illegal_access_error()

@app.route('/iot/bind-devices', methods=['POST'])
@verify_token
def iot_bind_devices():
    #绑定设备
    user_id = current_user_id()
    if user_id:
        data = readJsonData()
        device_id = data.get("id") #设备id
        if device_id:
            try:
                service_impl.bind_device(user_id=user_id, device_id=device_id)
                return ok_data()
            except Exception as e:
                traceback.print_exc()
                return error_data(str(e))
        else:
            return msissing_parameters_error()
    else:
        return illegal_access_error()

@app.route('/iot/active-device', methods=['POST'])
@verify_token
def iot_active_devices():
    #绑定设备
    user_id = current_user_id()
    if user_id:
        data = readJsonData()
        active_code = data.get("active_code") #设备id
        device_name = data.get("device_name") #设备名称
        if active_code!=None and device_name!=None:
            try:
                service_impl.active_device(user_id=user_id, active_code=active_code, device_name=device_name)
                return ok_data()
            except Exception as e:
                traceback.print_exc()
                return error_data(-1, str(e))
        else:
            return msissing_parameters_error()
    else:
        return illegal_access_error()

@app.route('/iot/modify-device-name', methods=['POST'])
@verify_token
def iot_moidify_device_name():
    #绑定设备
    user_id = current_user_id()
    if user_id:
        data = readJsonData()
        device_id = data.get("device_id") #设备id
        device_name = data.get("device_name") #设备名称
        if device_id!=None and device_name!=None:
            try:
                service_impl.modify_device_name(device_id=device_id, device_name=device_name)
                return ok_data()
            except Exception as e:
                traceback.print_exc()
                return error_data(str(e))
        else:
            return msissing_parameters_error()
    else:
        return illegal_access_error()

flask_app.register_blueprint(blueprint=app, url_prefix='/api/')

application = flask_app

if __name__ == "__main__":
    application.run(host='0.0.0.0')